package com.ironman.common.util;

import cn.hutool.core.collection.CollUtil;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class MathUtil {

    public static Double calculateAvg(List<Double> data) {
        // 计算平均值
        double mean = data.stream()
                .filter(Objects::nonNull)
                .mapToDouble(Double::doubleValue)
                .average()
                .orElse(Double.NaN);
        if (Double.isNaN(mean)) {
            return null;
        }
        return mean;
    }

    /**
     * 计算样本标准差（贝塞尔修正）
     *
     * @param data 输入数据集
     * @return 样本标准差
     * @throws IllegalArgumentException 当数据不足时抛出异常
     */
    public static Double calculateSampleStdDev(List<Double> data) {
        // 空值安全检查
        if (CollUtil.isEmpty(data)) {
            return null;
        }

        // 计算平均值
        double mean = data.stream()
                .filter(Objects::nonNull)
                .mapToDouble(Double::doubleValue)
                .average()
                .orElse(Double.NaN);
        if (Double.isNaN(mean)) {
            return null;
        }

        // 计算平方差总和
        double sumSquaredDiff = data.stream()
                .filter(Objects::nonNull)
                .mapToDouble(num -> Math.pow(num - mean, 2))
                .sum();

        // 贝塞尔修正（n-1）
        int n = data.size();
        if (n < 2) {
            return null;
        }

        // 计算标准差
        return Math.sqrt(sumSquaredDiff / (n - 1));
    }

    /**
     * 区间分组计数
     */
    public static Map<String, Long> countByRange(List<Double> data, int[] ranges) {
        return data.stream().collect(Collectors.groupingBy(n -> {
                    for (int i = 0; i < ranges.length - 1; i++) {
                        if (n >= ranges[i] && n < ranges[i + 1]) {
                            return String.format("%s-%s", ranges[i], ranges[i + 1]);
                        }
                    }
                    return "";
                },
                Collectors.counting()
        ));
    }
}
